
`include "defines.v"

module data_ctr(

    input                       id_rs1_r_ena_i,
    input                       id_rs2_r_ena_i,

    input       [`REG_BUS]      id_rs1_addr_i,
    input       [`REG_BUS]      id_rs2_addr_i,

    input       [`REG_WIDTH]    rs1_data_i,
    input       [`REG_WIDTH]    rs2_data_i,


    input                       exe_w_ena_i,    
    input                       mem_w_ena_i,    
    input                       wb_w_ena_i,
    input       [`REG_BUS]      exe_w_addr_i,
    input       [`REG_BUS]      mem_w_addr_i,
    input       [`REG_BUS]      wb_w_addr_i,
    input                       exe_data_valid_i,
    input                       mem_data_valid_i,
    input       [`REG_WIDTH]    exe_w_data_i,
    input       [`REG_WIDTH]    mem_w_data_i,
    input       [`REG_WIDTH]    wb_w_data_i,


    output wire [`REG_WIDTH]    id_rs1_data_o,
    output wire [`REG_WIDTH]    id_rs2_data_o,
    output wire                 id_hit_o   // to drive id_stall 


);
    wire id_exe_rs1_hit, id_mem_rs1_hit, id_wb_rs1_hit;
    wire id_exe_rs2_hit, id_mem_rs2_hit, id_wb_rs2_hit;
    

    assign id_exe_rs1_hit  = (id_rs1_addr_i == exe_w_addr_i) & exe_w_ena_i & id_rs1_r_ena_i & exe_data_valid_i;
    assign id_exe_rs2_hit  = (id_rs2_addr_i == exe_w_addr_i) & exe_w_ena_i & id_rs2_r_ena_i & exe_data_valid_i;
    assign id_mem_rs1_hit  = (id_rs1_addr_i == mem_w_addr_i) & mem_w_ena_i & id_rs1_r_ena_i & mem_data_valid_i;
    assign id_mem_rs2_hit  = (id_rs2_addr_i == mem_w_addr_i) & mem_w_ena_i & id_rs2_r_ena_i & mem_data_valid_i;
    assign id_wb_rs1_hit   = (id_rs1_addr_i == wb_w_addr_i ) & wb_w_ena_i  & id_rs1_r_ena_i;
    assign id_wb_rs2_hit   = (id_rs2_addr_i == wb_w_addr_i ) & wb_w_ena_i  & id_rs2_r_ena_i;
    assign id_hit_o        = (id_rs1_addr_i == exe_w_addr_i) & exe_w_ena_i & id_rs1_r_ena_i |
                             (id_rs2_addr_i == exe_w_addr_i) & exe_w_ena_i & id_rs2_r_ena_i |
                             (id_rs1_addr_i == mem_w_addr_i) & mem_w_ena_i & id_rs1_r_ena_i |
                             (id_rs2_addr_i == mem_w_addr_i) & mem_w_ena_i & id_rs2_r_ena_i;

    assign id_rs1_data_o = id_exe_rs1_hit ? exe_w_data_i :
                           id_mem_rs1_hit ? mem_w_data_i :
                           id_wb_rs1_hit  ? wb_w_data_i  :
                           rs1_data_i;

    assign id_rs2_data_o = id_exe_rs2_hit ? exe_w_data_i :
                           id_mem_rs2_hit ? mem_w_data_i :
                           id_wb_rs2_hit  ? wb_w_data_i  :
                           rs2_data_i;
                        
endmodule